<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Highscore - Boost C++ 库 - 文件系统</title>
<link rel="stylesheet" href="css/highscore.css" type="text/css">
<link rev="made" href="mailto:boris@highscore.de">
<link rel="home" href="frontpage.html" title="Boost C++ 库">
<link rel="up" href="frontpage.html" title="Boost C++ 库">
<link rel="prev" href="interprocesscommunication.html" title="第 8 章 进程间通讯">
<link rel="next" href="castoperators.html" title="第 10 章 类型转换操作符">
<link rel="chapter" href="introduction.html" title="第 1 章 简介">
<link rel="chapter" href="smartpointers.html" title="第 2 章 智能指针">
<link rel="chapter" href="functionobjects.html" title="第 3 章 函数对象">
<link rel="chapter" href="eventhandling.html" title="第 4 章 事件处理">
<link rel="chapter" href="asio.html" title="第 5 章 异步输入输出">
<link rel="chapter" href="asio.html" title="第 6 章 异步输入输出">
<link rel="chapter" href="asio.html" title="第 7 章 异步输入输出">
<link rel="chapter" href="interprocesscommunication.html" title="第 8 章 进程间通讯">
<link rel="chapter" href="filesystem.html" title="第 9 章 文件系统">
<link rel="chapter" href="castoperators.html" title="第 10 章 类型转换操作符">
<link rel="chapter" href="castoperators.html" title="第 11 章 类型转换操作符">
<link rel="chapter" href="castoperators.html" title="第 12 章 类型转换操作符">
<link rel="chapter" href="castoperators.html" title="第 13 章 类型转换操作符">
<link rel="chapter" href="castoperators.html" title="第 14 章 类型转换操作符">
<link rel="chapter" href="castoperators.html" title="第 15 章 类型转换操作符">
<link rel="chapter" href="castoperators.html" title="第 16 章 类型转换操作符">
<link rel="section" href="filesystem.html#filesystem_general" title="9.1. 概述">
<link rel="section" href="filesystem.html#filesystem_paths" title="9.2. 路径">
<link rel="section" href="filesystem.html#filesystem_files_and_directories" title="9.3. 文件与目录">
<link rel="section" href="filesystem.html#filesystem_fstream" title="9.4. 文件流">
<link rel="section" href="filesystem.html#filesystem_exercises" title="9.5. 练习">
<meta http-equiv="pics-label" content='(pics-1.1 "http://www.icra.org/ratingsv02.html" l gen true for "http://www.highscore.de" r (nz 1 vz 1 lz 1 oz 1 cz 1) gen true for "http://highscore.de" r (nz 1 vz 1 lz 1 oz 1 cz 1))'>
<meta http-equiv="Content-Style-Type" content="text/css">
<meta http-equiv="Content-Script-Type" content="text/javascript">
<link href="http://www.highscore.de/favicon.ico" rel="shortcut icon" type="image/vnd.microsoft.icon">
</head>
<body>
<div lang="zh" class="docbook chapter" title="第 9 章 文件系统">
<p class="title">Boost C++ 库</p>
<script type="text/javascript">
          var titlepage = "导言";
        
      var titles = new Array(titlepage,
      
        "第 1 章 简介",
      
        "第 2 章 智能指针",
      
        "第 3 章 函数对象",
      
        "第 4 章 事件处理",
      
        "第 5 章 异步输入输出",
      
        "第 6 章 异步输入输出",
      
        "第 7 章 异步输入输出",
      
        "第 8 章 进程间通讯",
      
        "第 9 章 文件系统",
      
        "第 10 章 类型转换操作符",
      
        "第 11 章 类型转换操作符",
      
        "第 12 章 类型转换操作符",
      
        "第 13 章 类型转换操作符",
      
        "第 14 章 类型转换操作符",
      
        "第 15 章 类型转换操作符",
      
        "第 16 章 类型转换操作符",
      
      "");

      
          var titlehtml = "frontpage.html";
        
      var filenames = new Array(titlehtml,
      
        "introduction.html",
      
        "smartpointers.html",
      
        "functionobjects.html",
      
        "eventhandling.html",
      
        "asio.html",
      
        "asio.html",
      
        "asio.html",
      
        "interprocesscommunication.html",
      
        "filesystem.html",
      
        "castoperators.html",
      
        "castoperators.html",
      
        "castoperators.html",
      
        "castoperators.html",
      
        "castoperators.html",
      
        "castoperators.html",
      
        "castoperators.html",
      
      "");

      
      document.open();
      document.write('<form action="" class="toc">');
      document.write('<select size="1" onchange="location.href=options[selectedIndex].value">');
      for (var i = 0; i < titles.length && i < filenames.length; ++i) {
        if (titles[i] != "" && filenames[i] != "") {
          document.write('<option');
          document.write(' value="' + filenames[i] + '"');
          var expr = new RegExp('[/\]' + filenames[i] + '$');
          if (expr.test(location.href)) {
            document.write(' selected="selected"');
          }
          document.write('>' + titles[i] + '<\/option>');
        }
      }
      document.write('<\/select>');
      document.write('<\/form>');
      document.close();
      
    </script><noscript><p class="toc"><a href="toc.html">目录</a></p></noscript>
<hr class="hrhead">
<h1 class="title">
<a name="filesystem"></a>第 9 章 文件系统</h1>
<hr>
<div class="toc">
<h3>目录</h3>
<ul>
<li><span class="sect1"><a href="filesystem.html#filesystem_general">9.1 概述</a></span></li>
<li><span class="sect1"><a href="filesystem.html#filesystem_paths">9.2 路径</a></span></li>
<li><span class="sect1"><a href="filesystem.html#filesystem_files_and_directories">9.3 文件与目录</a></span></li>
<li><span class="sect1"><a href="filesystem.html#filesystem_fstream">9.4 文件流</a></span></li>
<li><span class="sect1"><a href="filesystem.html#filesystem_exercises">9.5 练习</a></span></li>
</ul>
</div>
<p class="license"><a href="http://creativecommons.org/licenses/by-nc-nd/3.0/de/deed.zh" rel="license" target="_top"><img src="img/88x31_cc_logo.gif" alt="" width="88" height="31"></a> 该书采用 <a href="http://creativecommons.org/licenses/by-nc-nd/3.0/de/deed.zh" rel="license" target="_top">Creative Commons License</a> 授权</p>
<hr>
<h2 class="title">
<a name="filesystem_general"></a>9.1. 概述</h2>
<div class="sect1"><p>库 <a class="link" href="http://www.boost.org/libs/filesystem/">Boost.Filesystem</a>
    简化了处理文件和目录的工作。 它提供了一个名为 <code class="classname">boost::filesystem::path</code>
    的类，可以对路径进行处理。 另外，还有多个函数用于创建目录或验证某个给定文件的有效性。</p></div>
<hr>
<h2 class="title">
<a name="filesystem_paths"></a>9.2. 路径</h2>
<div class="sect1">
<p><code class="classname">boost::filesystem::path</code> 是 Boost.Filesystem
    中的核心类，它表示路径的信息，并提供了处理路径的方法。</p>
<p>实际上，<code class="classname">boost::filesystem::path</code> 是
    <code class="code">boost::filesystem::basic_path&lt;std::string&gt;</code> 的一个
    <code class="code">typedef</code>。 此外还有一个
    <code class="classname">boost::filesystem::wpath</code> 是
    <code class="code">boost::filesystem::basic_path&lt;std::wstring&gt;</code> 的
    <code class="code">typedef</code>。</p>
<p>所有定义均位于 <span class="package">boost::filesystem</span> 名字空间，定义于 <code class="filename">boost/filesystem.hpp</code> 中。</p>
<p>可以通过传入一个字符串至 <code class="classname">boost::filesystem::path</code>
    类来构建一个路径。</p>
<pre class="programlisting">#include &lt;boost/filesystem.hpp&gt; 

int main() 
{ 
  boost::filesystem::path p1("C:\\"); 
  boost::filesystem::path p2("C:\\Windows"); 
  boost::filesystem::path p3("C:\\Program Files"); 
} </pre>
<ul class="programlisting"><li><a class="programlisting" href="src/9.2.1/main.cpp">下载源代码</a></li></ul>
<p>没有一个 <code class="classname">boost::filesystem::path</code>
    的构造函数会实际验证所提供路径的有效性，或检查给定的文件或目录是否存在。
    因此，<code class="classname">boost::filesystem::path</code> 甚至可以用无意义的路径来初始化。</p>
<pre class="programlisting">#include &lt;boost/filesystem.hpp&gt; 

int main() 
{ 
  boost::filesystem::path p1("..."); 
  boost::filesystem::path p2("\\"); 
  boost::filesystem::path p3("@:"); 
} </pre>
<ul class="programlisting"><li><a class="programlisting" href="src/9.2.2/main.cpp">下载源代码</a></li></ul>
<p>以上程序可以执行的原因是，路径其实只是字符串而已。
    <code class="classname">boost::filesystem::path</code>
    只是处理字符串罢了；文件系统没有被访问到。</p>
<p><code class="classname">boost::filesystem::path</code>
    特别提供了一些方法来以字符串方式获取一个路径。 有趣的是，有三种不同的方法。</p>
<pre class="programlisting">#include &lt;boost/filesystem.hpp&gt; 
#include &lt;iostream&gt; 

int main() 
{ 
  boost::filesystem::path p("C:\\Windows\\System"); 
  std::cout &lt;&lt; p.string() &lt;&lt; std::endl; 
  std::cout &lt;&lt; p.file_string() &lt;&lt; std::endl; 
  std::cout &lt;&lt; p.directory_string() &lt;&lt; std::endl; 
} </pre>
<ul class="programlisting"><li><a class="programlisting" href="src/9.2.3/main.cpp">下载源代码</a></li></ul>
<p><code class="methodname">string()</code> 方法返回一个所谓的可移植路径。 换句话说，就是
    Boost.Filesystem 用它自己预定义的规则来正规化给定的字符串。
    在以上例子中，<code class="methodname">string()</code> 返回
    <code class="computeroutput">C:/Windows/System</code>。 如你所见，Boost.Filesystem
    内部使用斜杠符 <code class="code">/</code> 作为文件名与目录名的分隔符。</p>
<p>可移植路径的目的是在不同的平台，如 Windows 或 Linux 之间，唯一地标识文件和目录。
    因此就不再需要使用预处理器宏来根据底层的操作系统进行路径的编码。 构建可移植路径的规则大多符合POSIX标准，在 <a class="link" href="http://www.boost.org/libs/filesystem/doc/reference.html">Boost.Filesystem
    参考手册</a> 给出。</p>
<p>请注意，<code class="classname">boost::filesystem::path</code>
    的构造函数同时支持可移植路径和平台相关路径。 在上面例子中所使用的路径 "C:\\Windows\\System" 就不是可移植路径，而是
    Windows 专用的。 它可以被 Boost.Filesystem 正确识别，但仅当该程序是在 Windows 操作系统下运行的时候！
    当程序运行于一个 POSIX 兼容的操作系统，如 Linux 时，<code class="methodname">string()</code> 将返回
    <code class="computeroutput">C:\Windows\System</code>。 因为在 Linux 中，反斜杠符
    <code class="code">\</code> 并不被用作分隔符，无论是可移植格式或原生格式，Boost.Filesystem
    都不会认为它是文件和目录的分隔符。</p>
<p>很多时候，都不能避免使用平台相关路径作为字符串。 一个例子就是，使用操作系统函数时必须要用平台相关的编码。 方法
    <code class="methodname">file_string()</code> 和
    <code class="methodname">directory_string()</code> 正是为此目的而提供的。</p>
<p>在上例中，这两个方法都会返回 <code class="computeroutput">C:\Windows\System</code> -
    与底层操作系统无关。 在 Windows 上这个字符串是有效路径，而在一个 Linux
    系统上则既不是可移植路径也不是平台相关路径，会象前面所说那样被解析。</p>
<p>以下例子使用一个可移植路径来初始化
    <code class="classname">boost::filesystem::path</code>。</p>
<pre class="programlisting">#include &lt;boost/filesystem.hpp&gt; 
#include &lt;iostream&gt; 

int main() 
{ 
  boost::filesystem::path p("/"); 
  std::cout &lt;&lt; p.string() &lt;&lt; std::endl; 
  std::cout &lt;&lt; p.file_string() &lt;&lt; std::endl; 
  std::cout &lt;&lt; p.directory_string() &lt;&lt; std::endl; 
} </pre>
<ul class="programlisting"><li><a class="programlisting" href="src/9.2.4/main.cpp">下载源代码</a></li></ul>
<p>由于 <code class="methodname">string()</code> 返回的是一个可移植路径，所以它与用于初始化
    <code class="classname">boost::filesystem::path</code>
    的字符串相同：<code class="computeroutput">/</code>。 但是
    <code class="methodname">file_string()</code> 和
    <code class="methodname">directory_string()</code> 方法则会因底层平台而返回不同的结果。 在 Windows
    中，它们都返回 <code class="computeroutput">\</code>，而在 Linux 中则都返回
    <code class="computeroutput">/</code>。</p>
<p>你可能会奇怪为什么会有两个不同的方法用来返回平台相关路径。
    到目前为止，在所看到的例子中，<code class="methodname">file_string()</code> 和
    <code class="methodname">directory_string()</code> 都是返回相同的值。 但是，有些操作系统可能会返回不同的结果。
    因为 Boost.Filesystem 的目标是支持尽可能多的操作系统，所以它提供了两个方法来适应这种情况。 即使你可能更为熟悉 Windows 或
    POSIX 系统如 Linux，但还是建议使用 <code class="methodname">file_string()</code>
    来取出文件的路径信息，且使用 <code class="methodname">directory_string()</code> 取出目录的路径信息。
    这无疑会增加代码的可移植性。</p>
<p><code class="classname">boost::filesystem::path</code>
    提供了几个方法来访问一个路径中的特定组件。</p>
<pre class="programlisting">#include &lt;boost/filesystem.hpp&gt; 
#include &lt;iostream&gt; 

int main() 
{ 
  boost::filesystem::path p("C:\\Windows\\System"); 
  std::cout &lt;&lt; p.root_name() &lt;&lt; std::endl; 
  std::cout &lt;&lt; p.root_directory() &lt;&lt; std::endl; 
  std::cout &lt;&lt; p.root_path() &lt;&lt; std::endl; 
  std::cout &lt;&lt; p.relative_path() &lt;&lt; std::endl; 
  std::cout &lt;&lt; p.parent_path() &lt;&lt; std::endl; 
  std::cout &lt;&lt; p.filename() &lt;&lt; std::endl; 
} </pre>
<ul class="programlisting"><li><a class="programlisting" href="src/9.2.5/main.cpp">下载源代码</a></li></ul>
<p>如果在是一个 Windows 操作系统上执行，则字符串 "C:\\Windows\\System" 被解释为一个平台相关的路径信息。
    因此，<code class="methodname">root_name()</code> 返回
    <code class="computeroutput">C:</code>,
    <code class="methodname">root_directory()</code> 返回
    <code class="computeroutput">/</code>, <code class="methodname">root_path()</code> 返回
    <code class="computeroutput">C:/</code>,
    <code class="methodname">relative_path()</code> 返回
    <code class="computeroutput">Windows/System</code>,
    <code class="methodname">parent_path()</code> 返回
    <code class="computeroutput">C:/Windows</code>, 而
    <code class="methodname">filename()</code> 返回
    <code class="computeroutput">System</code>。</p>
<p>如你所见，没有平台相关的路径信息被返回。 没有一个返回值包含反斜杠 <code class="code">\</code>，只有斜杠
    <code class="code">/</code>。 如果需要平台相关信息，则要使用 <code class="methodname">file_string()</code> 或
    <code class="methodname">directory_string()</code>。 为了使用这些路径中的单独组件，必须创建一个类型为
    <code class="classname">boost::filesystem::path</code> 的新对象并相应的进行初始化。</p>
<p>如果以上程序在 Linux 操作系统中执行，则返回值有所不同。 多数方法会返回一个空字符串，除了
    <code class="methodname">relative_path()</code> 和 <code class="methodname">filename()</code>
    会返回 <code class="computeroutput">C:\Windows\System</code>。 字符串
    "C:\\Windows\\System" 在 Linux 中被解释为一个文件名，这个字符串既不是某个路径的可移植编码，也不是一个被 Linux
    支持的平台相关编码。 因此，Boost.Filesystem 没有其它选择，只能将整个字符串解释为一个文件名。</p>
<p>Boost.Filesystem 还提供了其它方法来检查一个路径中是否包含某个特定子串。
    这些方法是：<code class="methodname">has_root_name()</code>,
    <code class="methodname">has_root_directory()</code>,
    <code class="methodname">has_root_path()</code>,
    <code class="methodname">has_relative_path()</code>,
    <code class="methodname">has_parent_path()</code> 和
    <code class="methodname">has_filename()</code>。 各个方法都是返回一个 <code class="type">bool</code>
    类型的值。</p>
<p>还有两个方法用于将一个文件名拆分为各个组件。 它们应当仅在 <code class="methodname">has_filename()</code>
    返回 <code class="literal">true</code> 时使用。 否则只会返回一个空字符串，因为如果没有文件名就没什么可拆分了。</p>
<pre class="programlisting">#include &lt;boost/filesystem.hpp&gt; 
#include &lt;iostream&gt; 

int main() 
{ 
  boost::filesystem::path p("photo.jpg"); 
  std::cout &lt;&lt; p.stem() &lt;&lt; std::endl; 
  std::cout &lt;&lt; p.extension() &lt;&lt; std::endl; 
} </pre>
<ul class="programlisting"><li><a class="programlisting" href="src/9.2.6/main.cpp">下载源代码</a></li></ul>
<p>这个程序分别返回 <code class="computeroutput">photo</code> 给
    <code class="methodname">stem()</code>，以及 <code class="computeroutput">.jpg</code> 给
    <code class="methodname">extension()</code>。</p>
<p>除了使用各个方法调用来访问路径的各个组件以外，你还可以对组件本身进行迭代。</p>
<pre class="programlisting">#include &lt;boost/filesystem.hpp&gt; 
#include &lt;iostream&gt; 

int main() 
{ 
  boost::filesystem::path p("C:\\Windows\\System"); 
  for (boost::filesystem::path::iterator it = p.begin(); it != p.end(); ++it) 
    std::cout &lt;&lt; *it &lt;&lt; std::endl; 
} </pre>
<ul class="programlisting"><li><a class="programlisting" href="src/9.2.7/main.cpp">下载源代码</a></li></ul>
<p>如果是在 Windows 上执行，则该程序将相继输出 <code class="computeroutput">C:</code>,
    <code class="computeroutput">/</code>,
    <code class="computeroutput">Windows</code> 和
    <code class="computeroutput">System</code>。 在其它的操作系统如 Linux 上，输出结果则是
    <code class="computeroutput">C:\Windows\System</code>。</p>
<p>前面的例子示范了不同的方法来访问路径中的各个组件，以下例子则示范了修改路径信息的方法。</p>
<pre class="programlisting">#include &lt;boost/filesystem.hpp&gt; 
#include &lt;iostream&gt; 

int main() 
{ 
  boost::filesystem::path p("C:\\"); 
  p /= "Windows\\System"; 
  std::cout &lt;&lt; p.string() &lt;&lt; std::endl; 
} </pre>
<ul class="programlisting"><li><a class="programlisting" href="src/9.2.8/main.cpp">下载源代码</a></li></ul>
<p>通过使用重载的 <code class="methodname">operator/=()</code> 操作符，这个例子将一个路径添加到另一个之上。 在
    Windows 中，该程序将输出 <code class="computeroutput">C:\Windows\System</code>。 在
    Linux 中，输出将会是 <code class="computeroutput">C:\/Windows\System</code>，因为斜杠符
    <code class="code">/</code> 是文件与目录的分隔符。 这也是重载 <code class="methodname">operator/=()</code>
    操作符的原因：毕竟，斜杠是这个方法名的一个部分。</p>
<p>除了 <code class="methodname">operator/=()</code>，Boost.Filesystem 只提供了
    <code class="methodname">remove_filename()</code> 和
    <code class="methodname">replace_extension()</code> 方法来修改路径信息。</p>
</div>
<hr>
<h2 class="title">
<a name="filesystem_files_and_directories"></a>9.3. 文件与目录</h2>
<div class="sect1">
<p><code class="classname">boost::filesystem::path</code> 的各个方法内部其实只是对字符串进行处理。
    它们可以用来访问一个路径的各个组件、相互添加路径等等。</p>
<p>为了处理硬盘上的物理文件和目录，提供了几个独立的函数。 这些函数需要一个或多个
    <code class="classname">boost::filesystem::path</code>
    类型的参数，并且在其内部会调用操作系统功能来处理这些文件或目录。</p>
<p>在介绍各个函数之前，很重要的一点是要弄明白出现错误时会发生什么。 所有要在内部访问操作系统功能的函数都有可能失败。
    在失败的情况下，将抛出一个类型为
    <code class="exceptionname">boost::filesystem::filesystem_error</code> 的异常。
    这个类是派生自 <code class="exceptionname">boost::system::system_error</code> 的，因此适用于
    Boost.System 框架。</p>
<p>除了继承自父类 <code class="exceptionname">boost::system::system_error</code> 的
    <code class="methodname">what()</code> 和 <code class="methodname">code()</code>
    方法以外，还有另外两个方法：<code class="methodname">path1()</code> 和
    <code class="methodname">path2()</code>。 它们均返回一个类型为
    <code class="classname">boost::filesystem::path</code> 的对象，因此在发生错误时可以很容易地确定路径信息 -
    即使是对那些需要两个 <code class="classname">boost::filesystem::path</code> 参数的函数。</p>
<p>多数函数存在两个变体：在失败时，一个会抛出类型为
    <code class="exceptionname">boost::filesystem::filesystem_error</code>
    的异常，而另一个则返回类型为 <code class="classname">boost::system::error_code</code> 的对象。
    对于后者，需要对返回值进行明确的检查以确定是否出错。</p>
<p>以下例子介绍了一个函数，它可以查询一个文件或目录的状态。</p>
<pre class="programlisting">#include &lt;boost/filesystem.hpp&gt; 
#include &lt;iostream&gt; 

int main() 
{ 
  boost::filesystem::path p("C:\\"); 
  try 
  { 
    boost::filesystem::file_status s = boost::filesystem::status(p); 
    std::cout &lt;&lt; boost::filesystem::is_directory(s) &lt;&lt; std::endl; 
  } 
  catch (boost::filesystem::filesystem_error &amp;e) 
  { 
    std::cerr &lt;&lt; e.what() &lt;&lt; std::endl; 
  } 
} </pre>
<ul class="programlisting"><li><a class="programlisting" href="src/9.3.1/main.cpp">下载源代码</a></li></ul>
<p><code class="function">boost::filesystem::status()</code> 返回一个
    <code class="classname">boost::filesystem::file_status</code>
    类型的对象，该对象可以被传递给其它辅助函数来评估。 例如，如果查询的是一个目录的状态，则
    <code class="function">boost::filesystem::is_directory()</code> 将返回
    <code class="literal">true</code>。 除了
    <code class="function">boost::filesystem::is_directory()</code>，还有其它函数，如
    <code class="function">boost::filesystem::is_regular_file()</code>,
    <code class="function">boost::filesystem::is_symlink()</code> 和
    <code class="function">boost::filesystem::exists()</code>，它们都会返回一个 <code class="type">bool</code>
    类型的值。</p>
<p>除了 <code class="function">boost::filesystem::status()</code>，另一个名为
    <code class="function">boost::filesystem::symlink_status()</code> 的函数可用于查询一个符号链接的状态。
    在此情况下，实际上查询的是符号链接所指向的文件的状态。在 Windows 中，符号链接以 <code class="filename">lnk</code> 文件扩展名识别。</p>
<p>另有一组函数可用于查询文件和目录的属性。</p>
<pre class="programlisting">#include &lt;boost/filesystem.hpp&gt; 
#include &lt;iostream&gt; 

int main() 
{ 
  boost::filesystem::path p("C:\\Windows\\win.ini"); 
  try 
  { 
    std::cout &lt;&lt; boost::filesystem::file_size(p) &lt;&lt; std::endl; 
  } 
  catch (boost::filesystem::filesystem_error &amp;e) 
  { 
    std::cerr &lt;&lt; e.what() &lt;&lt; std::endl; 
  } 
} </pre>
<ul class="programlisting"><li><a class="programlisting" href="src/9.3.2/main.cpp">下载源代码</a></li></ul>
<p>函数 <code class="function">boost::filesystem::file_size()</code>
    以字节数返回一个文件的大小。</p>
<pre class="programlisting">#include &lt;boost/filesystem.hpp&gt; 
#include &lt;iostream&gt; 
#include &lt;ctime&gt; 

int main() 
{ 
  boost::filesystem::path p("C:\\Windows\\win.ini"); 
  try 
  { 
    std::time_t t = boost::filesystem::last_write_time(p); 
    std::cout &lt;&lt; std::ctime(&amp;t) &lt;&lt; std::endl; 
  } 
  catch (boost::filesystem::filesystem_error &amp;e) 
  { 
    std::cerr &lt;&lt; e.what() &lt;&lt; std::endl; 
  } 
} </pre>
<ul class="programlisting"><li><a class="programlisting" href="src/9.3.3/main.cpp">下载源代码</a></li></ul>
<p>要获得一个文件最后被修改的时间，可使用
    <code class="function">boost::filesystem::last_write_time()</code>。</p>
<pre class="programlisting">#include &lt;boost/filesystem.hpp&gt; 
#include &lt;iostream&gt; 

int main() 
{ 
  boost::filesystem::path p("C:\\"); 
  try 
  { 
    boost::filesystem::space_info s = boost::filesystem::space(p); 
    std::cout &lt;&lt; s.capacity &lt;&lt; std::endl; 
    std::cout &lt;&lt; s.free &lt;&lt; std::endl; 
    std::cout &lt;&lt; s.available &lt;&lt; std::endl; 
  } 
  catch (boost::filesystem::filesystem_error &amp;e) 
  { 
    std::cerr &lt;&lt; e.what() &lt;&lt; std::endl; 
  } 
} </pre>
<ul class="programlisting"><li><a class="programlisting" href="src/9.3.4/main.cpp">下载源代码</a></li></ul>
<p><code class="function">boost::filesystem::space()</code> 用于取回磁盘的总空间和剩余空间。 它返回一个
    <code class="classname">boost::filesystem::space_info</code>
    类型的对象，其中定义了三个公有属性：<var>capacity</var>, <var>free</var> 和
    <var>available</var>。 这三个属性的类型均为
    <code class="type">boost::uintmax_t</code>，该类型定义于 Boost.Integer 库，通常是 <code class="code">unsigned
    long long</code> 的 typedef。 磁盘空间是以字节数来计算的。</p>
<p>目前所看到的函数都不会触及文件和目录本身，不过有另外几个函数可以用于创建、改名或删除文件和目录。</p>
<pre class="programlisting">#include &lt;boost/filesystem.hpp&gt; 
#include &lt;iostream&gt; 

int main() 
{ 
  boost::filesystem::path p("C:\\Test"); 
  try 
  { 
    if (boost::filesystem::create_directory(p)) 
    { 
      boost::filesystem::rename(p, "C:\\Test2"); 
      boost::filesystem::remove("C:\\Test2"); 
    } 
  } 
  catch (boost::filesystem::filesystem_error &amp;e) 
  { 
    std::cerr &lt;&lt; e.what() &lt;&lt; std::endl; 
  } 
} </pre>
<ul class="programlisting"><li><a class="programlisting" href="src/9.3.5/main.cpp">下载源代码</a></li></ul>
<p>以上例子应该是自解释的。 仔细察看，可以看到传递给各个函数的不一定是
    <code class="classname">boost::filesystem::path</code> 类型的对象，也可以是一个简单的字符串。
    这是可以的，因为 <code class="classname">boost::filesystem::path</code>
    提供了一个非显式的构造函数，可以从简单的字符串转换为 <code class="classname">boost::filesystem::path</code>
    类型的对象。 这实际上简化了 Boost.Filesystem 的使用，因为可以无须显式创建一个对象。</p>
<p>还有其它的函数，如 <code class="function">create_symlink()</code> 用于创建符号链接，以及
    <code class="function">copy_file()</code> 用于复制文件或目录。</p>
<p>以下例子中介绍了一个函数，基于一个文件名或一小节路径来创建一个绝对路径。</p>
<pre class="programlisting">#include &lt;boost/filesystem.hpp&gt; 
#include &lt;iostream&gt; 

int main() 
{ 
  try 
  { 
    std::cout &lt;&lt; boost::filesystem::complete("photo.jpg") &lt;&lt; std::endl; 
  } 
  catch (boost::filesystem::filesystem_error &amp;e) 
  { 
    std::cerr &lt;&lt; e.what() &lt;&lt; std::endl; 
  } 
} </pre>
<ul class="programlisting"><li><a class="programlisting" href="src/9.3.6/main.cpp">下载源代码</a></li></ul>
<p>输出哪个路径是由该程序运行时所处的路径决定的。 例如，如果该例子从 <code class="filename">C:\</code> 运行，输出将是
    <code class="computeroutput">C:/photo.jpg</code>。</p>
<p>请再次留意斜杠符 <code class="code">/</code>! 如果想得到一个平台相关的路径，则需要初始化一个
    <code class="classname">boost::filesystem::path</code> 类型的对象，且必须调用
    <code class="methodname">file_string()</code>。</p>
<p>要取出一个相对于其它目录的绝对路径，可将第二个参数传递给
    <code class="function">boost::filesystem::complete()</code>。</p>
<pre class="programlisting">#include &lt;boost/filesystem.hpp&gt; 
#include &lt;iostream&gt; 

int main() 
{ 
  try 
  { 
    std::cout &lt;&lt; boost::filesystem::complete("photo.jpg", "D:\\") &lt;&lt; std::endl; 
  } 
  catch (boost::filesystem::filesystem_error &amp;e) 
  { 
    std::cerr &lt;&lt; e.what() &lt;&lt; std::endl; 
  } 
} </pre>
<ul class="programlisting"><li><a class="programlisting" href="src/9.3.7/main.cpp">下载源代码</a></li></ul>
<p>现在，该程序显示的是 <code class="computeroutput">D:/photo.jpg</code>。</p>
<p>最后，还有一个辅助函数用于取出当前工作目录，如下例所示。</p>
<pre class="programlisting">#include &lt;windows.h&gt; 
#include &lt;boost/filesystem.hpp&gt; 
#include &lt;iostream&gt; 

int main() 
{ 
  try 
  { 
    std::cout &lt;&lt; boost::filesystem::current_path() &lt;&lt; std::endl; 
    SetCurrentDirectory("C:\\"); 
    std::cout &lt;&lt; boost::filesystem::current_path() &lt;&lt; std::endl; 
  } 
  catch (boost::filesystem::filesystem_error &amp;e) 
  { 
    std::cerr &lt;&lt; e.what() &lt;&lt; std::endl; 
  } 
} </pre>
<ul class="programlisting"><li><a class="programlisting" href="src/9.3.8/main.cpp">下载源代码</a></li></ul>
<p>以上程序只能在 Windows 中执行，这是 <code class="function">SetCurrentDirectory()</code>
    函数的原因。 这个函数更换了当前工作目录，因此对
    <code class="function">boost::filesystem::current_path()</code> 的两次调用将返回不同的结果。</p>
<p>函数 <code class="function">boost::filesystem::initial_path()</code>
    用于返回应用程序开始执行时所处的目录。 但是，这个函数取决于操作系统的支持，因此如果需要可移植性，建议不要使用。
    在这种情况下，Boost.Filesystem 文档中建议的方法是，可以在程序开始时保存
    <code class="function">boost::filesystem::current_path()</code> 的返回值，以备后用。</p>
</div>
<hr>
<h2 class="title">
<a name="filesystem_fstream"></a>9.4. 文件流</h2>
<div class="sect1">
<p>C++ 标准在 <code class="filename">fstream</code>
    头文件中定义了几个文件流。 这些流不能接受 <code class="classname">boost::filesystem::path</code>
    类型的参数。 由于 Boost.Filesystem 库很有可能被包含在 C++ 标准的 Technical Report 2
    中，所以这些文件流将通过相应的构造函数来进行扩展。 为了当前可以让文件流与类型为
    <code class="classname">boost::filesystem::path</code> 的路径信息一起工作，可以使用头文件 <code class="filename">boost/filesystem/fstream.hpp</code>。
    它提供了对文件流所需的扩展，这些都是基于 Technical Report 2 即将加入 C++ 标准中的。</p>
<pre class="programlisting">#include &lt;boost/filesystem/fstream.hpp&gt; 
#include &lt;iostream&gt; 

int main() 
{ 
  boost::filesystem::path p("test.txt"); 
  boost::filesystem::ofstream ofs(p); 
  ofs &lt;&lt; "Hello, world!" &lt;&lt; std::endl; 
} </pre>
<ul class="programlisting"><li><a class="programlisting" href="src/9.4.1/main.cpp">下载源代码</a></li></ul>
<p>不仅是构造函数，还有 <code class="methodname">open()</code> 方法也需要重载，以接受类型为
    <code class="classname">boost::filesystem::path</code> 的参数。</p>
</div>
<hr>
<h2 class="title">
<a name="filesystem_exercises"></a>9.5. 练习</h2>
<div class="sect1">
<p class="solution">
              You can buy 
              <a target="_top" href="http://en.highscore.de/shop/index.php?p=boost-solution">solutions to all exercises</a>
              in this book as a ZIP file. 
            </p>
<ol><li class="listitem"><p>创建一个程序，该程序为位于应用程序当前工作目录的上一层目录中的一个名为
        <code class="computeroutput">data.txt</code> 的文件创建一个绝对路径。 例如，如果该程序从
        <code class="computeroutput">C:\Program Files\Test</code> 执行，则应显示
        <code class="computeroutput">C:\Program Files\data.txt</code>。</p></li></ol>
</div>
</div>
<hr class="hrfoot">
<p class="copyright">版权 © 2008-2010 
        <a class="link" href="mailto:boris@highscore.de">Boris Schäling</a>
      </p>
</body>
</html>
